package cn.luyou.admin.service.impl;

import cn.hutool.json.JSONUtil;
import cn.luyou.admin.dto.GeneratePaperDTO;
import cn.luyou.admin.dto.RuleConfigDTO;
import cn.luyou.admin.entity.ExamPaper;
import cn.luyou.admin.entity.ExamPaperQuestion;
import cn.luyou.admin.entity.ExamRule;
import cn.luyou.admin.entity.Question;
import cn.luyou.admin.mapper.ExamPaperMapper;
import cn.luyou.admin.service.ExamPaperQuestionService;
import cn.luyou.admin.service.ExamPaperService;
import cn.luyou.admin.service.ExamRuleService;
import cn.luyou.admin.service.QuestionService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.stream.Collectors;

@Service
public class ExamPaperServiceImpl extends ServiceImpl<ExamPaperMapper, ExamPaper> implements ExamPaperService {

    @Autowired
    private ExamRuleService examRuleService;

    @Autowired
    private QuestionService questionService;

    @Autowired
    private ExamPaperQuestionService examPaperQuestionService;

    @Override
    public IPage<ExamPaper> getPapers(Integer pageNum, Integer pageSize, String keyword) {
        LambdaQueryWrapper<ExamPaper> wrapper = new LambdaQueryWrapper<>();
        if (StringUtils.hasText(keyword)) {
            wrapper.like(ExamPaper::getPaperName, keyword)
                    .or()
                    .like(ExamPaper::getSubject, keyword);
        }
        wrapper.orderByDesc(ExamPaper::getCreatedTime);
        return this.page(new Page<>(pageNum, pageSize), wrapper);
    }

    @Override
    @Transactional
    public ExamPaper generatePaper(GeneratePaperDTO generatePaperDTO, Long userId) {
        // 获取规则
        ExamRule rule = examRuleService.getById(generatePaperDTO.getRuleId());
        if (rule == null) {
            throw new IllegalArgumentException("规则不存在");
        }
        
        // 解析规则配置
        RuleConfigDTO ruleConfig = JSONUtil.toBean(rule.getRuleConfig(), RuleConfigDTO.class);
        
        // 创建试卷
        ExamPaper paper = new ExamPaper()
                .setPaperName(generatePaperDTO.getPaperName())
                .setSubject(rule.getSubject())
                .setTotalScore(rule.getTotalScore())
                .setDuration(rule.getDuration())
                .setStatus(0)
                .setCreatedBy(userId);
        this.save(paper);
        
        // 根据规则生成试题
        List<ExamPaperQuestion> paperQuestions = new ArrayList<>();
        int questionOrder = 1;
        
        for (RuleConfigDTO.QuestionTypeConfig typeConfig : ruleConfig.getQuestionTypes()) {
            // 获取符合条件的题目
            List<Question> questions = questionService.list(new LambdaQueryWrapper<Question>()
                    .eq(Question::getQuestionType, typeConfig.getType())
                    .eq(Question::getDifficulty, typeConfig.getDifficulty())
                    .eq(Question::getSubject, rule.getSubject()));
            
            if (questions.size() < typeConfig.getCount()) {
                throw new IllegalArgumentException("题库中符合条件的题目数量不足");
            }
            
            // 随机选择题目
            List<Question> selectedQuestions = randomSelectQuestions(questions, typeConfig.getCount());
            
            // 添加到试卷题目列表
            for (Question question : selectedQuestions) {
                ExamPaperQuestion paperQuestion = new ExamPaperQuestion()
                        .setPaperId(paper.getId())
                        .setQuestionId(question.getId())
                        .setQuestionScore(typeConfig.getScorePerQuestion())
                        .setQuestionOrder(questionOrder++);
                paperQuestions.add(paperQuestion);
            }
        }
        
        // 保存试卷题目
        examPaperQuestionService.savePaperQuestions(paper.getId(), paperQuestions);
        
        return paper;
    }

    @Override
    @Transactional
    public void updatePaper(ExamPaper paper) {
        ExamPaper existingPaper = this.getById(paper.getId());
        if (existingPaper == null) {
            throw new IllegalArgumentException("试卷不存在");
        }
        
        // 检查试卷名是否与其他试卷冲突
        if (!existingPaper.getPaperName().equals(paper.getPaperName())) {
            if (this.count(new LambdaQueryWrapper<ExamPaper>()
                    .eq(ExamPaper::getPaperName, paper.getPaperName())) > 0) {
                throw new IllegalArgumentException("试卷名称已存在");
            }
        }
        
        this.updateById(paper);
    }

    @Override
    @Transactional
    public void deletePaper(Long id) {
        ExamPaper paper = this.getById(id);
        if (paper == null) {
            throw new IllegalArgumentException("试卷不存在");
        }
        
        // 删除试卷题目
        examPaperQuestionService.deletePaperQuestions(id);
        
        // 删除试卷
        this.removeById(id);
    }

    @Override
    @Transactional
    public void updateStatus(Long id, Integer status) {
        ExamPaper paper = this.getById(id);
        if (paper == null) {
            throw new IllegalArgumentException("试卷不存在");
        }
        
        paper.setStatus(status);
        this.updateById(paper);
    }

    @Override
    public List<Question> getPaperQuestions(Long paperId) {
        // 获取试卷题目关联
        List<ExamPaperQuestion> paperQuestions = examPaperQuestionService.getPaperQuestions(paperId);
        
        // 获取题目详情
        List<Long> questionIds = paperQuestions.stream()
                .map(ExamPaperQuestion::getQuestionId)
                .collect(Collectors.toList());
        
        if (questionIds.isEmpty()) {
            return new ArrayList<>();
        }
        
        // 按试卷题目顺序返回题目列表
        List<Question> questions = questionService.listByIds(questionIds);
        return paperQuestions.stream()
                .map(pq -> questions.stream()
                        .filter(q -> q.getId().equals(pq.getQuestionId()))
                        .findFirst()
                        .orElse(null))
                .filter(q -> q != null)
                .collect(Collectors.toList());
    }

    private List<Question> randomSelectQuestions(List<Question> questions, int count) {
        List<Question> selectedQuestions = new ArrayList<>();
        Random random = new Random();
        
        // 创建题目索引列表
        List<Integer> indices = new ArrayList<>();
        for (int i = 0; i < questions.size(); i++) {
            indices.add(i);
        }
        
        // 随机选择指定数量的题目
        for (int i = 0; i < count; i++) {
            int randomIndex = random.nextInt(indices.size());
            selectedQuestions.add(questions.get(indices.get(randomIndex)));
            indices.remove(randomIndex);
        }
        
        return selectedQuestions;
    }
} 